﻿using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using PAT.Data;
using PAT.Data.Bases;
using PAT.Entities;
using PAT.Services;
using PAT.Util;

namespace PAT.Util
{
    /// <summary>
    /// 
    /// </summary>
    public class Common
    {
        /// <summary>
        /// Constructor vacio
        /// </summary>
        public Common() { }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatEmpresa> GetEmpresasPorEstado(Boolean estado)
        {
            PatEmpresaParameterBuilder filtros = new PatEmpresaParameterBuilder();
            filtros.AppendEquals(PatEmpresaColumn.Activo, "true");
            return DataRepository.PatEmpresaProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public TList<PatCatalogoVehiculo> GetCatalogosVehiculoByEstado(Boolean estado)
        {
            PatCatalogoVehiculoParameterBuilder filtros = new PatCatalogoVehiculoParameterBuilder();
            filtros.AppendEquals(PatCatalogoVehiculoColumn.Activo, estado.ToString());
            return DataRepository.PatCatalogoVehiculoProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatKit> GetKitsPorEstado(Boolean estado)
        {
            PatKitParameterBuilder filtros = new PatKitParameterBuilder();
            filtros.AppendEquals(PatKitColumn.Activo, estado.ToString());
            return DataRepository.PatKitProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatTaller> GetTallerPorEstado(Boolean estado)
        {
            PatTallerParameterBuilder filtros = new PatTallerParameterBuilder();
            filtros.AppendEquals(PatTallerColumn.Activo, estado.ToString());
            return DataRepository.PatTallerProvider.Find(filtros.GetParameters());
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="codigoEmpresa"></param>
        /// <returns></returns>
        public TList<PatTaller> GetTallerPorEmpresa(Int32 codigoEmpresa)
        {
            TList<PatEmpresaTaller> empresaTalleres = DataRepository.PatEmpresaTallerProvider.GetByIdEmpresa(codigoEmpresa);
            DataRepository.PatEmpresaTallerProvider.DeepLoad(empresaTalleres, true, Data.DeepLoadType.IncludeChildren, typeof(PatTaller));
            TList<PatTaller> talleres = new TList<PatTaller>();
            foreach(PatEmpresaTaller empresaTaller in empresaTalleres)
                talleres.Add(empresaTaller.IdTallerSource);
            return talleres;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="codigoTaller"></param>
        /// <param name="tipoEmpleado"></param>
        /// <param name="fechaConsulta"></param>
        /// <param name="citasPorFecha"></param>
        /// <returns></returns>
        public DataSet GetSourceCitasTaller(Int32 codigoTaller, TipoEmpleado tipoEmpleado, DateTime fechaConsulta, ref TList<PatCitaTaller> citasPorFecha, ref TList<PatEmpleado> empleados)
        {
            // 1. Se realiza la consulta de cuales son los empleados asociados al taller
            empleados = GetEmpleadosPorTaller(codigoTaller, tipoEmpleado);
            // 2. Se consultan los parametros de configuración del taller seleccionado
            PatConfiguracionTaller configuracionEspecifica = GetConfiguracionTaller(codigoTaller);
            // 3. Se consultan las citas disponibles por esta fecha
            citasPorFecha = GetCitasPorFecha(codigoTaller, fechaConsulta);
            // 4. Se configuran las columnas de la fuente de datos asociada a las citas de taller
            DataTable dtCitas = new DataTable("dtCitas");
            dtCitas.Columns.Add(new DataColumn("Hora",typeof(String)));
            // Ahora se agregan columnas por cada empleado de taller encontrado 
            foreach (PatEmpleado empleado in empleados)
                dtCitas.Columns.Add(new DataColumn(empleado.Nombres + " " + empleado.Apellidos, typeof(String)));
            // Ahora se construye el rango de horas en las que se pueden tomar citas de taller
            TimeSpan rangoAtencion = configuracionEspecifica.HoraFinalizacionRecepcion - configuracionEspecifica.HoraInicioRecepcion;
            int contadorCotaSuperior = rangoAtencion.Hours * ((int)configuracionEspecifica.CantidadCitasXHora);
            double horaDuracionCitas = (double)((double)1 / (double)configuracionEspecifica.CantidadCitasXHora);
            DateTime contadorFechas = configuracionEspecifica.HoraInicioRecepcion;
            for (int i = 0; i < contadorCotaSuperior; i++)
            {
                if (contadorFechas <= configuracionEspecifica.HoraFinalizacionRecepcion)
                {
                    String rangoFechas = contadorFechas.ToString("hh:mm tt") + " - " + contadorFechas.AddHours(horaDuracionCitas).ToString("hh:mm tt");
                    DataRow drNew = dtCitas.NewRow();
                    drNew["Hora"] = rangoFechas;
                    dtCitas.Rows.Add(drNew);
                    contadorFechas = contadorFechas.AddHours(horaDuracionCitas);
                }
            }
            DataSet dsCitas = new DataSet();
            dsCitas.Tables.Add(dtCitas);
            return dsCitas;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="codigoTaller"></param>
        /// <param name="tipoEmpleado"></param>
        /// <returns></returns>
        public TList<PatEmpleado> GetEmpleadosPorTaller(Int32 codigoTaller, TipoEmpleado tipoEmpleado)
        {
            PatEmpleadoParameterBuilder filtros = new PatEmpleadoParameterBuilder();
            filtros.AppendEquals(PatEmpleadoColumn.IdTaller, codigoTaller.ToString());
            filtros.AppendEquals(PatEmpleadoColumn.IdTipoEmpleado, ((Int32)tipoEmpleado).ToString());
            return DataRepository.PatEmpleadoProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="codigoTaller"></param>
        /// <returns></returns>
        public PatConfiguracionTaller GetConfiguracionTaller(Int32 codigoTaller)
        {
            return DataRepository.PatConfiguracionTallerProvider.GetByIdTaller(codigoTaller);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="codigoTaller"></param>
        /// <param name="fechaConsulta"></param>
        /// <returns></returns>
        public TList<PatCitaTaller> GetCitasPorFecha(Int32 codigoTaller, DateTime fechaConsulta)
        {
            PatCitaTallerParameterBuilder filtros = new PatCitaTallerParameterBuilder();
            filtros.AppendEquals(PatCitaTallerColumn.IdTaller, codigoTaller.ToString());
            filtros.AppendEquals(PatCitaTallerColumn.FechaCita, fechaConsulta.ToString(ConfigurationManager.AppSettings["DateFormat"]));
            return DataRepository.PatCitaTallerProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="nuevaCita"></param>
        public void AlmacenarCita(PatCitaTaller nuevaCita)
        {
            DataRepository.PatCitaTallerProvider.Save(nuevaCita); 
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <param name="documento"></param>
        /// <returns></returns>
        public TList<PatDocumento> GetDocumentosPorEstadoYTipo(Boolean estado, TiposDocumento documento)
        {
            PatDocumentoParameterBuilder filtros = new PatDocumentoParameterBuilder();
            filtros.AppendEquals(PatDocumentoColumn.Activo, estado.ToString());
            filtros.AppendEquals(PatDocumentoColumn.IdTipoDocumento, ((int)documento).ToString());
            return DataRepository.PatDocumentoProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatCargoOrden> GetCargoOrdenPorEstado(Boolean estado)
        {
            PatCargoOrdenParameterBuilder filtros = new PatCargoOrdenParameterBuilder();
            filtros.AppendEquals(PatCargoOrdenColumn.Activo, estado.ToString());
            return DataRepository.PatCargoOrdenProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatTrabajoOrden> GetTrabajoOrdenPorEstado(Boolean estado)
        {
            PatTrabajoOrdenParameterBuilder filtros = new PatTrabajoOrdenParameterBuilder();
            filtros.AppendEquals(PatTrabajoOrdenColumn.Activo, estado.ToString());
            return DataRepository.PatTrabajoOrdenProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatListaPreciosTaller> GetListaPreciosTallerPorEstado(Boolean estado)
        {
            PatListaPreciosTallerParameterBuilder filtros = new PatListaPreciosTallerParameterBuilder();
            filtros.AppendEquals(PatListaPreciosTallerColumn.Activo, estado.ToString());
            return DataRepository.PatListaPreciosTallerProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatItemListaPrecios> GetListaPreciosItemsPorEstado(Boolean estado)
        {
            PatItemListaPreciosParameterBuilder filtros = new PatItemListaPreciosParameterBuilder();
            filtros.AppendEquals(PatItemListaPreciosColumn.Activo, estado.ToString());
            return DataRepository.PatItemListaPreciosProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatCatalogoVehiculo> GetCatalogosPorEstado(Boolean estado)
        {
            PatCatalogoVehiculoParameterBuilder filtros = new PatCatalogoVehiculoParameterBuilder();
            filtros.AppendEquals(PatCatalogoVehiculoColumn.Activo, estado.ToString());
            return DataRepository.PatCatalogoVehiculoProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatColor> GetColorPorEstado(Boolean estado)
        {
            PatColorParameterBuilder filtros = new PatColorParameterBuilder();
            filtros.AppendEquals(PatColorColumn.Activo, estado.ToString());
            return DataRepository.PatColorProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatNivelCombustible> GetNivelCombustiblePorEstado(Boolean estado)
        {
            PatNivelCombustibleParameterBuilder filtros = new PatNivelCombustibleParameterBuilder();
            filtros.AppendEquals(PatNivelCombustibleColumn.Activo, estado.ToString());
            return DataRepository.PatNivelCombustibleProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatAccesorio> GetAccesoriosPorEstado(Boolean estado)
        {
            PatAccesorioParameterBuilder filtros = new PatAccesorioParameterBuilder();
            filtros.Append(PatAccesorioColumn.Activo, estado.ToString());
            return DataRepository.PatAccesorioProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatEstadoCita> GetEstadosCitaPorEstado(Boolean estado)
        {
            PatEstadoCitaParameterBuilder filtros = new PatEstadoCitaParameterBuilder();
            filtros.Append(PatEstadoCitaColumn.Activo, estado.ToString());
            return DataRepository.PatEstadoCitaProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idEstado"></param>
        /// <returns></returns>
        public PatEstadoCita GetEstadoCitaPorId(Byte idEstado)
        {
            return DataRepository.PatEstadoCitaProvider.GetByIdEstadoCita(idEstado);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idCatologo"></param>
        /// <returns></returns>
        public TList<PatKit> GetKitActivoPorCatalogo(Int32 idCatologo)
        {
            PatKitParameterBuilder filtros = new PatKitParameterBuilder();
            filtros.Append(PatKitColumn.IdGrupoCatalogo, idCatologo.ToString());
            filtros.Append(PatKitColumn.Activo, (true).ToString());
            return DataRepository.PatKitProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idCatalogo"></param>
        /// <param name="idListaPrecio"></param>
        /// <returns></returns>
        public TList<PatKit> GetKitActivoPorCatalogoPorListaPrecio(Int32 idCatalogo, Int32 idListaPrecio)
        {
            PatKitParameterBuilder filtros = new PatKitParameterBuilder();
            filtros.Append(PatKitColumn.IdGrupoCatalogo, idCatalogo.ToString());
            filtros.Append(PatKitColumn.IdListaPrecios, idListaPrecio.ToString());
            filtros.Append(PatKitColumn.Activo, (true).ToString());
            return DataRepository.PatKitProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idDocumento"></param>
        /// <returns></returns>
        public Int32 GetUltimoConsecutivoPorDocumento(Int32 idDocumento)
        {
            PatDocumento instanciaDocumento = DataRepository.PatDocumentoProvider.GetByIdDocumento(idDocumento);
            if (instanciaDocumento != null)
                return (instanciaDocumento.UltimoConsecutivoUsado + 1);
            else
                return -1;
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="idCatalogo"></param>
        /// <returns></returns>
        public String GetVINBasicoPorCatalogo(Int32 idCatalogo)
        {
            PatCatalogoVehiculo instanciaCatalogo = DataRepository.PatCatalogoVehiculoProvider.GetByIdCatalogo(idCatalogo);
            if (instanciaCatalogo != null)
                return instanciaCatalogo.VinBasico;
            else
                return String.Empty;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="placa"></param>
        /// <returns></returns>
        public PatVehiculo GetVehiculoPorPlaca(String placa)
        {
            PatVehiculoParameterBuilder filtros = new PatVehiculoParameterBuilder();
            filtros.Append(PatVehiculoColumn.Placa, placa);
            TList<PatVehiculo> listaVehiculos = DataRepository.PatVehiculoProvider.Find(filtros.GetParameters());
            if (listaVehiculos.Count > 0)
            {
                DataRepository.PatVehiculoProvider.DeepLoad(listaVehiculos[0], true);
                return listaVehiculos[0];
            }
            else
                return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idCliente"></param>
        /// <returns></returns>
        public PatCliente GetClientePorId(Int32 idCliente)
        {
            return DataRepository.PatClienteProvider.GetByIdCliente(idCliente);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idKit"></param>
        /// <param name="deepLoad"></param>
        /// <returns></returns>
        public PatKit GetKitPorId(Int32 idKit, Boolean deepLoad)
        {
            PatKit instanciaKit = DataRepository.PatKitProvider.GetByIdKit(idKit);
            if(deepLoad)
                DataRepository.PatKitProvider.DeepLoad(instanciaKit, true, DeepLoadType.IncludeChildren, typeof(TList<PatKitItem>), typeof(TList<PatKitOperacion>));
            return instanciaKit;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idProducto"></param>
        /// <param name="idCatalogo"></param>
        /// <returns></returns>
        public Int32 GetUsoXVehiculo(Int32 idProducto, Int32 idCatalogo)
        {
            PatItemCatalogo itemCatalogo = DataRepository.PatItemCatalogoProvider.GetByIdItemInventarioIdCatalogo(idProducto, idCatalogo);
            if (itemCatalogo != null)
                return itemCatalogo.CantidadXCatalogo;
            else
                return -1;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idProducto"></param>
        /// <returns></returns>
        public PatItemInventario GetItemCatalogoPorId(Int32 idProducto)
        {
            return DataRepository.PatItemInventarioProvider.GetByIdItemInventario(idProducto);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idProducto"></param>
        /// <param name="idListaPrecio"></param>
        /// <returns></returns>
        public Decimal GetPrecioItemXListaPrecios(Int32 idProducto, Byte idListaPrecio)
        {
            PatItemInventarioListaPrecios itemListaPrecio = DataRepository.PatItemInventarioListaPreciosProvider.GetByIdItemInventarioIdListaPreciosItem(idProducto, idListaPrecio);
            if (itemListaPrecio != null)
                return itemListaPrecio.Precio;
            else
                return -1;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idOperacion"></param>
        /// <returns></returns>
        public PatTempario GetOperacionPorId(Int32 idOperacion)
        {
            return DataRepository.PatTemparioProvider.GetByIdOperacion(idOperacion);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idCargoOrden"></param>
        /// <returns></returns>
        public PatCargoOrden GetCargoOrdenPorId(Byte idCargoOrden)
        {
            return DataRepository.PatCargoOrdenProvider.GetByIdCargoOrden(idCargoOrden);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idCatalogo"></param>
        /// <param name="idOperacion"></param>
        /// <returns></returns>
        public Decimal GetTiempoOperacion(Int16 idCatalogo, Int32 idOperacion, Byte idCargo)
        {
            Decimal tiempoOperacion = 0;
            PatTiempoTaller instanciaTiempoTaller = DataRepository.PatTiempoTallerProvider.GetByIdGrupoCatalogoIdOperacion(idCatalogo, idOperacion);
            if (instanciaTiempoTaller != null)
            {
                switch (idCargo)
                {
                    case 1:
                    case 2:
                    default:
                        tiempoOperacion = instanciaTiempoTaller.TiempoCliente;
                        break;
                    case 3:
                        tiempoOperacion = instanciaTiempoTaller.TiempoGarantia;
                        break;
                    case 4:
                        tiempoOperacion = instanciaTiempoTaller.TiempoMecanico;
                        break;
                }
            }
            else
            {
                PatTempario instanciaOperacion = this.GetOperacionPorId(idOperacion);
                tiempoOperacion = instanciaOperacion.TiempoEstandar;
            }
            return tiempoOperacion;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idOperacion"></param>
        /// <param name="idListaPrecio"></param>
        /// <param name="idCargo"></param>
        /// <param name="tiempo"></param>
        /// <param name="valorOperacion"></param>
        /// <param name="valorIva"></param>
        public void GetValorOperacion(Int32 idOperacion, Int32 idListaPrecio, Byte idCargo, Decimal tiempo, ref Decimal valorOperacion, ref Decimal valorIva)
        {
            Decimal valorHora = 0;
            PatListaPreciosTaller instanciaListaPrecio = DataRepository.PatListaPreciosTallerProvider.GetByIdListaPrecios(idListaPrecio);
            if (instanciaListaPrecio != null)
            {
                switch (idCargo)
                {
                    case 1:
                    case 2:
                    default:
                        valorHora = instanciaListaPrecio.ValorHoraCliente;
                        break;
                    case 3:
                        valorHora = instanciaListaPrecio.ValorHoraGarantia;
                        break;
                    case 4:
                        valorHora = instanciaListaPrecio.ValorHoraInterno;
                        break;
                }
            }
            PatTempario instanciaOperacion = DataRepository.PatTemparioProvider.GetByIdOperacion(idOperacion);
            if (instanciaOperacion.ExcentaDeIva)
            {
                valorOperacion = tiempo * valorHora;
                valorIva = 0;
            }
            else
            {
                valorOperacion = (tiempo * valorHora) + ((tiempo * valorHora) * Convert.ToDecimal(0.16));
                valorIva = ((tiempo * valorHora) * Convert.ToDecimal(0.16));
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatCausalGarantia> GetCausalGarantiaPorEstado(Boolean estado)
        {
            PatCausalGarantiaParameterBuilder filtros = new PatCausalGarantiaParameterBuilder();
            filtros.Append(PatCausalGarantiaColumn.Activo, estado.ToString());
            return DataRepository.PatCausalGarantiaProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idTipoOperacion"></param>
        /// <param name="idTaller"></param>
        /// <returns></returns>
        public PatEmpleado GetEmpleadoMenorCargaTrabajo(Int16 idTipoOperacion, Int32 idTaller)
        {
            DataSet dsQuery = DataRepository.PatEmpleadoProvider.GetHorasTrabajoXTipoOperacion(idTipoOperacion);
            if (dsQuery.Tables[0].Rows.Count > 0)
            { 
                // Se debe buscar si existe algun registro que concuerde con el id del taller
                DataRow[] seleccion = dsQuery.Tables[0].Select("ID_TALLER = " + idTaller.ToString(),"TotalTiempo ASC");
                if (seleccion.Length > 0)
                    return DataRepository.PatEmpleadoProvider.GetByIdEmpleado(Convert.ToInt32(seleccion[0]["ID_EMPLEADO"]));
                else
                    return null;
            }
            else
                return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idEstadoOperacion"></param>
        /// <returns></returns>
        public PatEstadoOperacion GetEstadoOperacionPorId(Byte idEstadoOperacion)
        {
            return DataRepository.PatEstadoOperacionProvider.GetByIdEstadoOperacion(idEstadoOperacion);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="valorInicial"></param>
        /// <param name="idTaller"></param>
        /// <param name="idMecanico"></param>
        /// <returns></returns>
        public DateTime GetEstimadoEntregaOT(DateTime valorInicial, Int32 idTaller, Decimal value)
        { 
            // Se deben traer los valores de Inicio y fin de trabajo en el el taller indicado
            PatConfiguracionTaller configuracionTaller = DataRepository.PatConfiguracionTallerProvider.GetByIdTaller(idTaller);
            // 
            DateTime nuevoValor = valorInicial.AddHours(Convert.ToDouble(value));
            if (value > 0)
            {
                // Se debe revisar si nuevoValor es mayor que la hora de cierre de taller
                if (nuevoValor.TimeOfDay > configuracionTaller.HoraFinalizacinMecanicos.TimeOfDay)
                {
                    // Se calcula la diferencia de tiempo
                    TimeSpan diferencia = nuevoValor.TimeOfDay - configuracionTaller.HoraFinalizacinMecanicos.TimeOfDay;
                    // Se da el valor a nuevoValor de valorInicial + 1 dia con la hora de apertura de taller 
                    nuevoValor = Convert.ToDateTime(valorInicial.AddDays(1).ToString("yyyy-MM-dd") + " " + configuracionTaller.HoraInicioMecanicos.ToString("HH:mm:ss"));
                    // A nuevo valor se le agrega la diferencia encontrada
                    nuevoValor.AddHours(diferencia.Hours);
                }
            }
            else
            {
                // Se debe revisar si nuevoValor es menor que la hora de cierre de taller
                if (nuevoValor.TimeOfDay < configuracionTaller.HoraInicioMecanicos.TimeOfDay)
                {
                    // Se calcula la diferencia de tiempo
                    TimeSpan diferencia = configuracionTaller.HoraFinalizacinMecanicos.TimeOfDay - nuevoValor.TimeOfDay;
                    // Se da el valor a nuevoValor de valorInicial - 1 dia con la hora de cierre de taller 
                    nuevoValor = Convert.ToDateTime(valorInicial.AddDays(-1).ToString("yyyy-MM-dd") + " " + configuracionTaller.HoraFinalizacinMecanicos.ToString("HH:mm:ss"));
                    // A nuevo valor se le agrega la diferencia encontrada
                    nuevoValor.AddHours(diferencia.Hours * (-1));
                }
            }
            return nuevoValor;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="estado"></param>
        /// <returns></returns>
        public TList<PatTipoPropietario> GetTipoPropietarioPorEstado(Boolean estado)
        {
            PatTipoPropietarioParameterBuilder filtros = new PatTipoPropietarioParameterBuilder();
            filtros.AppendEquals(PatTipoPropietarioColumn.Activo, estado.ToString());
            return DataRepository.PatTipoPropietarioProvider.Find(filtros.GetParameters());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="instanciaVehiculo"></param>
        /// <param name="instanciaOrdenTrabajo"></param>
        /// <param name="AccesoriosOrdenTrabajo"></param>
        /// <param name="ItemsAsociadosOrdenTrabajo"></param>
        /// <param name="OperacionesAsociadasOrdenTrabajo"></param>
        /// <param name="KitsAsociadosOrdenTrabajo"></param>
        /// <param name="instanciaOrdenTrabajoGarantia"></param>
        /// <param name="instanciaOrdenTrabajoSeguros"></param>
        /// <param name="idCodigoDocumentoTransferencia"></param>
        /// <param name="NumeroTransferencia"></param>
        /// <param name="idCargoTransferencia"></param>
        /// <param name="idItemListaPrecio"></param>
        /// <returns></returns>
        public String GuardarOrdenTrabajoCompleta(  PatVehiculo instanciaVehiculo, 
                                                    PatOrdenTrabajo instanciaOrdenTrabajo, 
                                                    TList<PatOrdenTrabajoAccesorio> AccesoriosOrdenTrabajo, 
                                                    TList<PatTransferenciaDetalle> ItemsAsociadosOrdenTrabajo, 
                                                    TList<PatOrdenTrabajoOperacion> OperacionesAsociadasOrdenTrabajo, 
                                                    TList<PatKit> KitsAsociadosOrdenTrabajo,
                                                    PatOrdenTrabajoGarantia instanciaOrdenTrabajoGarantia,
                                                    PatOrdenTrabajoSeguros instanciaOrdenTrabajoSeguros,
                                                    Int32 idCodigoDocumentoTransferencia, 
                                                    Int32 NumeroTransferencia,
                                                    Byte idCargoTransferencia,
                                                    Byte idItemListaPrecio
                                                    )
        {
            String errorMessage = String.Empty;
            
            using (TransactionManager instanciaTransactionManager = DataRepository.Provider.CreateTransaction())
            {
                try
                {
                    instanciaTransactionManager.BeginTransaction();
                    DataRepository.PatVehiculoProvider.Save(instanciaTransactionManager, instanciaVehiculo);
                    // Se almacena el objeto con la informacion de la orden de trabajo
                    instanciaOrdenTrabajo.IdVehiculo = instanciaVehiculo.IdVehiculo;
                    DataRepository.PatOrdenTrabajoProvider.Save(instanciaTransactionManager, instanciaOrdenTrabajo);
                    // Se agrega el valor de documento de orden y el numero de orden en los objetos del arreglo AccesoriosOrdenTrabajo
                    foreach (PatOrdenTrabajoAccesorio instanciaAccesorio in AccesoriosOrdenTrabajo)
                    {
                        instanciaAccesorio.IdDocumento = instanciaOrdenTrabajo.IdDocumento;
                        instanciaAccesorio.NumeroOrden = instanciaOrdenTrabajo.NumeroOrden;
                        instanciaAccesorio.IdAccesorioSource = null;
                        instanciaAccesorio.IdDocumentoNumeroOrdenSource = null;
                    }
                    DataRepository.PatOrdenTrabajoAccesorioProvider.Save(instanciaTransactionManager, AccesoriosOrdenTrabajo);
                    // Se genera y almacena un objeto tipo PAT_TRANSFERENCIA
                    PatTransferencia instanciaTransferencia = new PatTransferencia();
                    instanciaTransferencia.IdDocumento = idCodigoDocumentoTransferencia;
                    instanciaTransferencia.NumeroTransferencia = NumeroTransferencia;
                    instanciaTransferencia.FechaTransferencia = DateTime.Now;
                    instanciaTransferencia.Activo = true;
                    instanciaTransferencia.IdCargoTransferencia = idCargoTransferencia;
                    instanciaTransferencia.IdItemListaPrecio = idItemListaPrecio;
                    DataRepository.PatTransferenciaProvider.Save(instanciaTransactionManager, instanciaTransferencia);
                    // Se almacena el detalle de la transferencia que viene en el arreglo ItemsAsociadosOrdenTrabajo
                    foreach (PatTransferenciaDetalle instanciaTransferenciaDetalle in ItemsAsociadosOrdenTrabajo)
                    {
                        instanciaTransferenciaDetalle.IdDocumento = idCodigoDocumentoTransferencia;
                        instanciaTransferenciaDetalle.NumeroTransferencia = NumeroTransferencia;
                        instanciaTransferenciaDetalle.IdDocumentoNumeroTransferenciaSource = null;
                        instanciaTransferenciaDetalle.IdItemInventarioSource = null;
                    }
                    DataRepository.PatTransferenciaDetalleProvider.Save(instanciaTransactionManager, ItemsAsociadosOrdenTrabajo);
                    // Se almacena la relacion entre transferencia y orden de trabajo PAT_ORDEN_TRABAJO_TRANSFERENCIA
                    PatOrdenTrabajoTransferencia instanciaOrdenTrabajoTransferencia = new PatOrdenTrabajoTransferencia();
                    instanciaOrdenTrabajoTransferencia.IdDocumentoOrden = instanciaOrdenTrabajo.IdDocumento;
                    instanciaOrdenTrabajoTransferencia.NumeroOrden = instanciaOrdenTrabajo.NumeroOrden;
                    instanciaOrdenTrabajoTransferencia.IdDocumentoTransferencia = idCodigoDocumentoTransferencia;
                    instanciaOrdenTrabajoTransferencia.NumeroTransferencia = NumeroTransferencia;
                    DataRepository.PatOrdenTrabajoTransferenciaProvider.Save(instanciaTransactionManager, instanciaOrdenTrabajoTransferencia);
                    // Se almacenan los kits asociados a la orden de trabajo
                    TList<PatOrdenTrabajoKit> kitsOrdenTrabajo = new TList<PatOrdenTrabajoKit>();
                    foreach (PatKit instanciaKit in KitsAsociadosOrdenTrabajo)
                    {
                        PatOrdenTrabajoKit instanciaKitsOrdenTrabajo = new PatOrdenTrabajoKit();
                        instanciaKitsOrdenTrabajo.IdDocumento = instanciaOrdenTrabajo.IdDocumento;
                        instanciaKitsOrdenTrabajo.NumeroOrden = instanciaOrdenTrabajo.NumeroOrden;
                        instanciaKitsOrdenTrabajo.IdKit = instanciaKit.IdKit;
                        kitsOrdenTrabajo.Add(instanciaKitsOrdenTrabajo);
                    }
                    DataRepository.PatOrdenTrabajoKitProvider.Save(instanciaTransactionManager, kitsOrdenTrabajo);
                    // Se agrega la informacion de garantia 
                    if (instanciaOrdenTrabajoGarantia != null)
                    {
                        instanciaOrdenTrabajoGarantia.IdDocumento = instanciaOrdenTrabajo.IdDocumento;
                        instanciaOrdenTrabajoGarantia.NumeroOrden = instanciaOrdenTrabajo.NumeroOrden;
                        instanciaOrdenTrabajoGarantia.IdDocumentoNumeroOrdenSource = null;
                        DataRepository.PatOrdenTrabajoGarantiaProvider.Save(instanciaTransactionManager, instanciaOrdenTrabajoGarantia);
                    }
                    // Se agrega la informacion de seguros
                    if (instanciaOrdenTrabajoSeguros != null)
                    {
                        instanciaOrdenTrabajoSeguros.IdDocumento = instanciaOrdenTrabajo.IdDocumento;
                        instanciaOrdenTrabajoSeguros.NumeroOrden = instanciaOrdenTrabajo.NumeroOrden;
                        instanciaOrdenTrabajoSeguros.IdDocumentoNumeroOrdenSource = null;
                        DataRepository.PatOrdenTrabajoSegurosProvider.Save(instanciaTransactionManager, instanciaOrdenTrabajoSeguros);
                    }
                    // Se agrega la informacion de las operaciones asociadas a la orden de trabajo
                    foreach (PatOrdenTrabajoOperacion instanciaOperacion in OperacionesAsociadasOrdenTrabajo)
                    {
                        instanciaOperacion.IdDocumento = instanciaOrdenTrabajo.IdDocumento;
                        instanciaOperacion.NumeroOrden = instanciaOrdenTrabajo.NumeroOrden;
                        instanciaOperacion.IdCargoOperacionSource = null;
                        instanciaOperacion.IdCausalGarantia1Source = null;
                        instanciaOperacion.IdCausalGarantia2Source = null;
                        instanciaOperacion.IdCausalGarantia3Source = null;
                        instanciaOperacion.IdCausalGarantia4Source = null;
                        instanciaOperacion.IdDocumentoNumeroOrdenSource = null;
                        instanciaOperacion.IdEmpleadoSource = null;
                        instanciaOperacion.IdEstadoOperacionSource = null;
                        instanciaOperacion.IdOperacionSource = null;
                        instanciaOperacion.ParentCollection = null;
                        instanciaOperacion.PatOrdenTrabajoOperacionObservacionCollection = null;
                    }
                    DataRepository.PatOrdenTrabajoOperacionProvider.Save(instanciaTransactionManager, OperacionesAsociadasOrdenTrabajo);
                    // Se actualizan los valores de ultimo documento de los documentos de transferencia y orden de trabajo
                    PatDocumento documentoOrdenTrabajo = DataRepository.PatDocumentoProvider.GetByIdDocumento(instanciaOrdenTrabajo.IdDocumento);
                    PatDocumento documentoTransferencia = DataRepository.PatDocumentoProvider.GetByIdDocumento(idCodigoDocumentoTransferencia);
                    documentoOrdenTrabajo.UltimoConsecutivoUsado = documentoOrdenTrabajo.UltimoConsecutivoUsado + 1;
                    documentoOrdenTrabajo.IdTipoDocumentoSource = null;
                    documentoOrdenTrabajo.ParentCollection = null;
                    documentoOrdenTrabajo.PatOrdenTrabajoCollection = null;
                    documentoOrdenTrabajo.PatTransferenciaCollection = null;
                    documentoTransferencia.UltimoConsecutivoUsado = documentoTransferencia.UltimoConsecutivoUsado + 1;
                    documentoTransferencia.IdTipoDocumentoSource = null;
                    documentoTransferencia.ParentCollection = null;
                    documentoTransferencia.PatOrdenTrabajoCollection = null;
                    documentoTransferencia.PatTransferenciaCollection = null;
                    DataRepository.PatDocumentoProvider.Save(instanciaTransactionManager, documentoOrdenTrabajo);
                    DataRepository.PatDocumentoProvider.Save(instanciaTransactionManager, documentoTransferencia);
                    // Se hace commit a la transaccion
                    instanciaTransactionManager.Commit();
                }
                catch (Exception ex)
                {
                    errorMessage = ex.Message;
                    instanciaTransactionManager.Rollback();
                }  
            }
            return errorMessage;
        }
    }
}
